grammar serializer;
    options {k=4;}
    tokens{
        RECORD    =    'clazz';
	COLLECTION = 	'collection';
	CASE =	'case';
	TYPEREF = 	'typeref';
    }
    @header {package metamodel; 
    	     import java.util.*;
             import metamodel.*;}


    WS: (' '|'\t'){$setType(Token.SKIP);};
    NEWLINE:('\r\n'| '\r'| '\n')
		{
			newline();
			$setType(Token.SKIP);
		};

    IDENTIFIER: (('a'..'z'|'A'..'Z')('a'..'z'|'A'..'Z')+);
	
    LPAREN: ('(');
    RPAREN: (')');
    DOLLAR: ('$');
    COMMA:(',');
    COLON:(':');
    SEMI:(';');
    DOT:('.');
    SLASH:('/');
   
COMMENT_1
        : '/*'
		   ( 
		   :	{ LA(2) != '/' }? '*'
		   |	'\r' '\n'		{newline();}
		   |	'\r'			{newline();}
		   |	'\n'			{newline();}
           |   ~('*' | '\n' | '\r')
		   )*
          '*/'
		{$setType(Token.SKIP);}
;


typepath returns [String navString]
 @init{
      navString="";
  }
    : (DOT DOT SLASH {navString+="../";})* ((id1=IDENTIFIER SLASH{navString+=$id1.getText();})* ()id2=IDENTIFIER{navString+=$id2.getText();})?
;


javaclass returns [String className]
    @init{className=new String();
      String tail;
      }

    : (part=IDENTIFIER DOT tail=javaclass {className=$part.getText()+"."+tail;}|
     part2=IDENTIFIER DOLLAR tail=javaclass {className=$part2.getText()+"$"+tail;})
    | rest=IDENTIFIER {className=$rest.getText();};


property returns [Property property]
  @init{String type;
   Clazz clazzz;
   property=null;
  }

: (id=IDENTIFIER COLON   (clazzz=clazz
                                     {property=new ObjectReference($id.getText(),clazzz);}
                          |   COLLECTION^ LPAREN! clazzz=clazz RPAREN!
                                     {property=new CollectionRef($id.getText(),clazzz);}
                          |   type=javaclass
                                     {property=new FlatProperty($id.getText(),type);}
                          )
   )   |  (
    
    fid=IDENTIFIER
                                     {property=new FlatProperty($fid.getText(),"java.lang.Object");}
 )         
;
propertylist returns [List list]
    @init{
        Property property,property1;
        list=new java.util.LinkedList();
    }
    :  property1=property {list.add(property1);
                          }
                  (COMMA aProperty=property {list.add(aProperty);})*
  ;

clazz returns [Clazz clazz]
    @init{
        String type;
        List propertyList=null;
        clazz=null;
        Clazz typecase;
        Clazz typeref;
    }
    : RECORD^ LPAREN! type=javaclass COMMA propertyList=propertylist RPAREN!
        {clazz=new Clazz(type,propertyList);}
        |
       aTypecase=typecase{
         clazz=aTypecase;
       }
       |
       aTyperef=typeref{
         clazz=aTyperef;
       }

    ;


recordlist returns [List list]
    @init{
        Clazz clazz,record1;
        list=new java.util.LinkedList();
    }
    :  record1=clazz {list.add(record1);
                      }
                  (COMMA aClazz=clazz {list.add(aClazz);})*
  ;

typeref returns [TypeReference ref]
	@init{
           ref=null;
           String path;
  }
  : TYPEREF LPAREN path=typepath RPAREN
               {ref=new TypeReference(path);}
;


typecase returns [PolyClazz clazz]
	@init{
                String type;
                List recordList=null;
                clazz=null;
             }
    : CASE^ LPAREN! type=javaclass COMMA recordList=recordlist RPAREN!
        { clazz=new PolyClazz(type,recordList); }
 ;


//collection returns [metamodel.CollectionRef]

